package com.wave.wavesystem.serve.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.OperatorSelectCondition;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import com.wave.common.enums.ErrorCode;
import com.wave.common.model.DeleteRequest;
import com.wave.common.model.KV;
import com.wave.common.model.Result;
import com.wave.common.util.Func;
import com.wave.waveoss.client.WaveOssClient;
import com.wave.wavesystem.serve.pojo.dto.fileupload.FileUploadDeleteRequest;
import com.wave.wavesystem.serve.pojo.entity.FileUpload;
import com.wave.wavesystem.serve.pojo.query.FileUploadQuery;
import com.wave.wavesystem.serve.pojo.vo.FileUploadVO;
import com.wave.wavesystem.serve.service.IFileUploadService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


@RestController
@RequestMapping("/fileUpload")
@RequiredArgsConstructor
@Tag(name = "文件上传接口-FileUploadController")
public class FileUploadController {

    private final IFileUploadService service;

    private final WaveOssClient ossClient;

    @PostMapping("/upload/single")
    @Operation(summary = "单文件上传")
    public Result<FileUpload> uploadSingle(@RequestPart("file") MultipartFile file,
                                           @RequestPart("userId") String userId) {
        if (Func.isEmpty(file)) {
            return Result.fail(ErrorCode.PARAMS_ERROR, "缺少上传文件");
        }
        Result<KV<String, String>> uploaded = ossClient.uploadFile(file);
        FileUpload fileUpload = fixFileUpload(file, userId, uploaded);
        fileUpload.setCreateUser(Long.valueOf(userId));
        fileUpload.setUpdateUser(Long.valueOf(userId));
        service.save(fileUpload);
        return Result.success(fileUpload);
    }

    @PostMapping("/upload/list")
    @Operation(summary = "多文件上传")
    public Result<List<FileUpload>> upload(@RequestPart("files") List<MultipartFile> files) {
        if (Func.isEmpty(files)) {
            return Result.fail(ErrorCode.PARAMS_ERROR, "缺少上传文件");
        }
        String userId = StpUtil.getLoginIdAsString();
        List<FileUpload> fileUploads = new ArrayList<>(files.size());
        for (MultipartFile file : files) {
            Result<KV<String, String>> uploaded = ossClient.uploadFile(file);
            if (!uploaded.isSuccess()) {
                continue;
            }
            FileUpload fileUpload = fixFileUpload(file, userId, uploaded);
            fileUpload.setCreateUser(Long.valueOf(userId));
            fileUpload.setUpdateUser(Long.valueOf(userId));
            fileUploads.add(fileUpload);
        }
        service.saveBatch(fileUploads);
        return Result.success(fileUploads);
    }

    /**
     * 组装 文件 实体
     *
     * @param file     文件
     * @param userId   用户id
     * @param uploaded 上传内容
     */
    @NotNull
    private FileUpload fixFileUpload(MultipartFile file, String userId, Result<KV<String, String>> uploaded) {
        FileUpload fileUpload = new FileUpload();
        fileUpload.setOriginalName(file.getOriginalFilename());
        fileUpload.setFileSize(file.getSize());
        fileUpload.setFileType(file.getContentType());
        fileUpload.setBucket(ossClient.getBucket());
        fileUpload.setEndpoint(ossClient.getEndpoint());
        fileUpload.setUserId(Long.parseLong(userId));
        fileUpload.setSortedName(uploaded.getData().getValue());
        fileUpload.setUrl(uploaded.getData().getKey());
        return fileUpload;
    }

    @PostMapping("/delete")
    @Operation(summary = "通过 ids 删除")
    public Result<Void> delete(@RequestBody FileUploadDeleteRequest deleteRequest) {
        if (Func.isNotEmpty(deleteRequest.getIds())) {
            List<Long> idList = Func.strToLongList(deleteRequest.getIds());
            List<FileUpload> files = service.queryChain().in(FileUpload::getId, idList).list();
            if (Func.isEmpty(files)) {
                return Result.fail(ErrorCode.NOT_FIND_ERROR);
            }
            files.forEach(fileUpload -> {
                ossClient.deleteFile(fileUpload.getSortedName());
            });
            service.removeByIds(Func.strToLongList(deleteRequest.getIds()));
        }
        if (Func.isNotEmpty(deleteRequest.getSortedName())) {
            QueryChain<FileUpload> removeWrapper = service.queryChain()
                    .eq(FileUpload::getSortedName, deleteRequest.getSortedName());
            boolean remove = service.remove(removeWrapper);
            if (remove) {
                ossClient.deleteFile(deleteRequest.getSortedName());
            }
        }
        return Result.success();
    }


    @PostMapping("/deleteByUrl")
    @Operation(summary = "通过 url 删除")
    public Result<Void> deleteByUrl(@RequestBody String url) {
        if (Func.isEmpty(url)) {
            return Result.fail(ErrorCode.NEED_PARAMS);
        }
        FileUpload one = service.queryChain().eq(FileUpload::getUrl, url).one();
        if (Func.isEmpty(one)) {
            return Result.fail(ErrorCode.NOT_FIND_ERROR);
        }
        ossClient.deleteFile(one.getSortedName());
        service.removeById(one.getId());
        return Result.success();
    }

    @PostMapping("/modify")
    @Operation(summary = "修改")
    public Result<FileUpload> modify(@RequestBody FileUpload entity) {
        service.updateById(entity);
        return Result.success(entity);
    }

    @GetMapping("/query")
    @Operation(summary = "根据条件查询")
    public Result<FileUpload> query(FileUploadQuery query) {
        FileUpload entity = service.getById(query.getId());
        return Result.success(entity);
    }

    @GetMapping("/list")
    @Operation(summary = "列表")
    public Result<List<FileUpload>> list(FileUploadQuery query) {
        QueryChain<FileUpload> queryChain = service.getQueryChain(query);
        List<FileUpload> list = service.list(queryChain);
        return Result.success(list);
    }

    @GetMapping("/page")
    @Operation(summary = "分页")
    public Result<Page<FileUploadVO>> page(FileUploadQuery query) {
        QueryChain<FileUpload> queryChain = service.getQueryChain(query);
        Page<FileUpload> page = service.page(new Page<>(query.getPageNum(), query.getPageSize()), queryChain);
        Page<FileUploadVO> FileUploadVOPage = new Page<>();
        BeanUtils.copyProperties(page, FileUploadVOPage);
        if (Func.isNotEmpty(page.getRecords())) {
            List<FileUploadVO> FileUploadVOS = page.getRecords().stream().map(FileUpload -> {
                FileUploadVO FileUploadVO = new FileUploadVO();
                BeanUtils.copyProperties(FileUpload, FileUploadVO);
                return FileUploadVO;
            }).toList();
            FileUploadVOPage.setRecords(FileUploadVOS);
        }
        return Result.success(FileUploadVOPage);
    }

    @GetMapping("/fileTypeList")
    @Operation(summary = "查询数据库里面有多少类型的文件")
    public Result<List<KV<String, String>>> fileTypeList() {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select("distinct fileType").from(FileUpload.class);
        List<String> types = service.listAs(queryWrapper, String.class);
        if (Func.isEmpty(types)) {
            return Result.success(Collections.emptyList());
        }
        List<KV<String,String>> list = types.stream().map(item -> new KV<>(item, item)).toList();
        return Result.success(list);
    }


}
